package top.goldenyear.porpoise.framework.web.core.generator;

import com.easy.query.core.proxy.ProxyEntityAvailable;
import javax.sql.DataSource;
import lombok.Setter;
import top.goldenyear.porpoise.framework.web.core.controller.BaseController;
import top.goldenyear.porpoise.framework.web.core.generator.config.GlobalConfig;
import top.goldenyear.porpoise.framework.web.core.generator.config.ModuleConfig;
import top.goldenyear.porpoise.framework.web.core.service.BaseService;

/**
 * 前端后分离模式代码生成器
 *
 * <p>只有生成器知道具体配置的module的含义，所以在 generator 中设置是否覆盖和生成哪些模块
 *
 * @author airhead
 */
@Setter
public class DeCoupledGenerator extends BaseGenerator {
  private DataSource dataSource;

  public DeCoupledGenerator() {
    super();
  }

  public DeCoupledGenerator(DataSource dataSource) {
    super();

    setDataSource(dataSource);
  }

  public DeCoupledGenerator enableOverwrite() {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.setOverwrite(true);
    return this;
  }

  public DeCoupledGenerator enableModel() {
    setModel(true);
    return this;
  }

  public DeCoupledGenerator enableService() {
    setService(true);
    return this;
  }

  public DeCoupledGenerator enableAdminController() {
    setAdminController(true);
    return this;
  }

  public DeCoupledGenerator enableVue() {
    setVueApi(true);
    setVueForm(true);
    setVueIndex(true);
    return this;
  }

  public DeCoupledGenerator enableVueApi() {
    setVueApi(true);
    return this;
  }

  public DeCoupledGenerator enableVueForm() {
    setVueForm(true);
    return this;
  }

  public DeCoupledGenerator enableVueIndex() {
    setVueIndex(true);
    return this;
  }

  public DeCoupledGenerator disableModel() {
    setModel(false);
    return this;
  }

  public DeCoupledGenerator disableService() {
    setService(false);
    return this;
  }

  public DeCoupledGenerator disableAdminController() {
    setAdminController(false);
    return this;
  }

  public DeCoupledGenerator disableVue() {
    setVueApi(false);
    setVueForm(false);
    setVueIndex(false);
    return this;
  }

  public DeCoupledGenerator disableVueApi() {
    setVueApi(false);
    return this;
  }

  public DeCoupledGenerator disableVueForm() {
    setVueForm(false);
    return this;
  }

  public DeCoupledGenerator disableVueIndex() {
    setVueIndex(false);
    return this;
  }

  protected void setModel(Boolean enable) {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.addGenerateConfig("model", enable);
    globalConfig.addGenerateConfig("model.base", enable);
  }

  protected void setService(Boolean enable) {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.addGenerateConfig("service", enable);
  }

  protected void setAdminController(Boolean enable) {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.addGenerateConfig("controller.admin", enable);
  }

  protected void setVueApi(Boolean enable) {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.addGenerateConfig("vue.api", enable);
  }

  protected void setVueIndex(Boolean enable) {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.addGenerateConfig("vue.index", enable);
  }

  protected void setVueForm(Boolean enable) {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig.addGenerateConfig("vue.form", enable);
  }

  @Override
  protected void initConfig() {
    GlobalConfig globalConfig = getGlobalConfig();
    globalConfig
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("model.base")
                .setOutputFile("#(sourcesRoot)/#(moduleFile)")
                .setFileSuffix(".java")
                .setClassPrefix("Base")
//                .setSuperClass(Model.class)
//                .setSuperInterface(IBean.class)
                .setTemplate("/templates/decoupled/java/model/baseModel.tpl")
                .setOverwrite(true))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("model")
                .setOutputFile("#(sourcesRoot)/#(moduleFile)")
                .setFileSuffix(".java")
                .setSuperInterface(ProxyEntityAvailable.class)
                .setTemplate("/templates/decoupled/java/model/model.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("service")
                .setOutputFile("#(sourcesRoot)/#(moduleFile)")
                .setFileSuffix(".java")
                .setClassSuffix("Service")
                .setSuperClass(BaseService.class)
                .setTemplate("/templates/decoupled/java/service/service.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("controller.admin")
                .setOutputFile("#(sourcesRoot)/#(moduleFile)")
                .setFileSuffix(".java")
                .setClassSuffix("AdminController")
                .setSuperClass(BaseController.class)
                .setTemplate("/templates/decoupled/java/controller/controller.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("ts.api")
                .setOutputFile(
                    "#(uiSourcesRoot)/src/service/api/#(cls.bizDomain)/#(moduleKebabFile)")
                .setFileSuffix(".ts")
                .setClassSuffix("")
                .setTemplate("/templates/decoupled/vue/api/api.ts.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("ts.index")
                .setOutputFile("#(uiSourcesRoot)/src/service/api/#(cls.bizDomain)/index.ts")
                .setFileSuffix(".ts")
                .setClassSuffix("")
                .setTemplate("/templates/decoupled/vue/api/index.ts.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("vue.index")
                .setOutputFile(
                    "#(uiSourcesRoot)/src/views/#(cls.bizDomain)/#(moduleKebab)/index.vue")
                .setFileSuffix(".vue")
                .setClassSuffix("")
                .setTemplate("/templates/decoupled/vue/views/index.vue.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("vue.search")
                .setOutputFile(
                    "#(uiSourcesRoot)/src/views/#(cls.bizDomain)/#(cls.getModuleKebab('model'))/modules/#(moduleKebabFile)")
                .setFileSuffix(".vue")
                .setClassSuffix("Search")
                .setTemplate("/templates/decoupled/vue/views/modules/search.vue.tpl"))
        .addModuleConfig(
            ModuleConfig.of()
                .setPackageConfig(globalConfig.getPackageConfig())
                .setModule("vue.form")
                .setOutputFile(
                    "#(uiSourcesRoot)/src/views/#(cls.bizDomain)/#(cls.getModuleKebab('model'))/modules/#(moduleKebabFile)")
                .setFileSuffix(".vue")
                .setClassSuffix("Drawer")
                .setTemplate("/templates/decoupled/vue/views/modules/form.vue.tpl"));
  }

  @Override
  protected void initMetaBuilder() {
    if (metaBuilder == null) {
      metaBuilder = new MetaBuilder(dataSource, this.getGlobalConfig());
    }
  }
}
